#include "Object.h"
#include "States.h"
#include "Clazz.h"
#include "Field.h"


using namespace mono;


template <>
void Object::PushArg<glm::vec3>(std::vector<void *> &addresses, glm::vec3 &arg)
{
    auto clazz = mono::States::GetClazz("Vec3");
    m_MonoObject = clazz->NewInstanceObject();
    //auto monoClass = clazz->m_Class;

    mono_field_set_value(m_MonoObject, clazz->GetField("x")->m_Field, &arg.x);
    mono_field_set_value(m_MonoObject, clazz->GetField("y")->m_Field, &arg.y);
    mono_field_set_value(m_MonoObject, clazz->GetField("z")->m_Field, &arg.z);

    addresses.push_back(m_MonoObject);

};

template <>
void Object::PushArg<int>(std::vector<void *> &addresses, int &arg)
{
    addresses.push_back(&arg);
};

template <>
void Object::PushArg<std::string>(std::vector<void *> &addresses, std::string &arg)
{
    addresses.push_back(mono_string_new(mono_domain_get(), arg.c_str()));
};

template <>
void Object::PushArg<float>(std::vector<void *> &addresses, float &arg)
{
    addresses.push_back(&arg);
};

template <>
glm::vec3 Object::As<glm::vec3>()
{
    auto clazz = mono::States::GetClazz("Vec3");
    glm::vec3 arg;

    MonoClassField *fieldX = mono_class_get_field_from_name(clazz->m_Class, "x");
    MonoClassField *fieldY = mono_class_get_field_from_name(clazz->m_Class, "y");
    MonoClassField *fieldZ = mono_class_get_field_from_name(clazz->m_Class, "z");

    mono_field_get_value(this->m_MonoObject, fieldX, &arg.x);
    mono_field_get_value(this->m_MonoObject, fieldY, &arg.y);
    mono_field_get_value(this->m_MonoObject, fieldZ, &arg.z);

    return arg;
};

template <>
int Object::As<int>()
{
    return *(int *)mono_object_unbox(m_MonoObject);
};

template <>
float Object::As<float>()
{
    return *(float*)mono_object_unbox(m_MonoObject);
};

template <>
std::string Object::As<std::string>()
{
    MonoString *resultString = (MonoString *)m_MonoObject;
    return mono_string_to_utf8(resultString);
};

